---
title: Choosing and Configuring an Engine
description: Learn how to select and configure the execution engine for plans and applies in Terrateam
---

import MermaidDiagram from "../../../../components/MermaidDiagram.astro";

Terrateam supports multiple execution engines, giving you the flexibility to choose the right tool for your workflow. Whether you are using standard Terraform, OpenTofu, Terragrunt, CDKTF, or even a fully custom engine, Terrateam makes it possible to configure plan and apply behavior that suits your needs.

You can define the [engine](/reference/configuration/engine) globally or override it per workflow by using the `engine` key in your `.terrateam/config.yml` file.

## Built In Engine Types

### Terraform (default)
```yaml
engine:
  name: terraform
```

### OpenTofu
```yaml
engine:
  name: tofu
  version: '1.9.0'
```

### Terragrunt
```yaml
engine:
  name: terragrunt
  tf_version: '1.11.1'
```

### CDKTF
```yaml
engine:
  name: cdktf
  tf_cmd: tofu
```

### Pulumi
```yaml
engine:
  name: pulumi
```

## Custom Engine

Use a custom engine when you need to perform tasks outside of standard Terraform or OpenTofu workflows, or when integrating with other infrastructure tools (e.g., custom wrappers, or legacy systems).

:::note[No Required Steps]
Custom engine does not require any specific steps - all steps are optional. You can define only the steps you need for your workflow. The `TERRATEAM_PLAN_FILE` environment variable is available in the apply phase if your plan step writes to it.
:::

### Example: Custom Engine

Below is an example configuration for a custom engine. Each key corresponds to a step in the Terrateam workflow. All steps are optional - define only what you need.

```yaml
engine:
  name: custom
  # The command to run during the init step (optional)
  init: ['echo', 'init']
  # The command to run during the plan step (optional)
  plan: ['my-custom-plan']
  # The command to produce a human-readable diff of the plan output (optional)
  diff: ['printf', '+ added foo\n- removed bar\n~ updated bar\n']
  # The command to run during the apply step (optional)
  apply: ['my-custom-apply']
  # The command to return output values as a JSON string (optional)
  outputs: ['echo', '{"foo": "bar"}']
```

**Highlights:**
- All steps (`init`, `plan`, `diff`, `apply`, `outputs`) are optional
- Define only the steps that make sense for your use case
- `$TERRATEAM_PLAN_FILE` environment variable is available to pass data from plan to apply
- Use this pattern to integrate with any tool or custom process

### How It Works
Each key corresponds to a step in the Terrateam workflow:

* `init` The command to run during the init step. Optional.
* `plan` The command to run during the plan step. Optional.
* `diff` The command to produce a human-readable diff of the plan output. Optional.
* `apply` The command to run during the apply step. Optional.
* `outputs` The command to return output values as a JSON string. Optional.

All steps are optional - you can define any combination of steps that makes sense for your use case.

:::note
The exit code of the `plan` script is important.  Custom engine uses the OpenTofu detailed exit code standard in that an exit code of `0` means there are changes in the plan and `2` means the plan was successful but there are no changes.  Any other exit code is considered a failure.
:::

## Per Workflow Engines
If you have different workflows (for example, dev and prod), you can override the engine configuration per workflow. Just nest the `engine` block inside a workflow definition.

```yaml
workflows:
  - tag_query: "development"
    engine:
      name: tofu
  - tag_query: "production"
    engine:
      name: terraform
```

## Best Practices
* Use per-workflow engine configurations to maximize flexibility.
* Use `tf_version` and `tf_cmd` to control which Terraform compatible CLI is invoked.
* For custom engines, test locally with the same environment variables Terrateam uses (especially `TERRATEAM_PLAN_FILE`).
